home *** CD-ROM | disk | FTP | other *** search
- /* Routines common to both the FTP client and server
- * Copyright 1991 Phil Karn, KA9Q
- */
- /* Mods by G1EMM */
- /* Mods by KO4KS */
- #include <stdio.h>
- #include "global.h"
- #include "mbuf.h"
- #include "socket.h"
- #include "proc.h"
- #include "ftp.h"
- #include "ftpcli.h"
- #include "usock.h"
- #ifdef LZW
- #include "lzw.h"
- #endif
- #include "md5.h"
-
-
- #define MD5BLOCK 64 /* Preferred MD5 block size */
-
- void
- hashit (hash, total, hmark)
- int hash;
- long total, *hmark;
- {
- while(hash && total >= (*hmark)+1000) {
- if (hash == V_HASH)
- tputc('#');
- if(hash == V_BYTE)
- tprintf("Bytes sent : %ld\r", total);
- *hmark += 1000;
- }
-
- }
-
-
- /* Send a file (opened by caller) on a network socket.
- * Normal return: count of bytes sent
- * Error return: -1
- * re-written by KO4KS to (1) reduce code size (2) all binary compression
- */
- long
- sendfile(fp,s,mode,hash)
- register FILE *fp; /* File to be sent */
- register int s; /* Socket to be sent on */
- int mode; /* Transfer mode */
- int hash; /* Print hash marks every BLKSIZE bytes */
- {
- register int c;
- register long total = 0;
- long hmark = 0;
- int oldf;
- struct usock *up;
- register struct mbuf *bp;
-
- if (mode == ASCII_TYPE) {
- oldf = setflush(s,-1);
- /* Let the newline mapping code in usputc() do the work */
- sockmode(s,SOCK_ASCII);
- } else
- sockmode(s,SOCK_BINARY);
- up = itop(s);
- if (mode != ASCII_TYPE && up->zout == NULLLZW) { /* also, not lzw compressed */
- for(;;){
- pwait (0); /* be a good neighbor and share! */
- bp = ambufw(BLKSIZE);
- if((bp->cnt = fread(bp->data,1,BLKSIZE,fp)) == 0){
- free_p(bp);
- break;
- }
- pwait (0); /* be a good neighbor and share! */
- total += bp->cnt;
- if(send_mbuf(s,bp,0,NULLCHAR,0) == -1){
- total = -1;
- break;
- }
- hashit (hash, total, &hmark);
- }
- } else {
-
- /* At this point, it is either ASCII_TYPE, or LZW compressed */
- while((c = getc(fp)) != EOF) {
- if (mode == ASCII_TYPE) {
- #ifndef TNOS_68K
- #if !defined(UNIX) && !defined(__TURBOC__)
- if(c == '\r'){
- /* Needed only if the OS uses a CR/LF
- * convention and getc doesn't do
- * an automatic translation
- */
- continue;
- }
- #endif
- #else
- if(c == '\l')
- continue;
- #endif
- if (!c)
- continue;
- }
- if(usputc(s,(char)c) == -1){
- total = -1;
- break;
- }
- total++;
- hashit (hash, total, &hmark);
- if (!(total % 256))
- pwait (0); /* be a good neighbor and share! */
- }
- }
- if (mode == ASCII_TYPE) {
- usflush(s);
- setflush(s,oldf);
- }
- if(hash)
- tputc('\n');
- return total;
- }
- /* Receive a file (opened by caller) from a network socket.
- * Normal return: count of bytes received
- * Error return: -1
- * re-written by KO4KS to (1) reduce code size (2) all binary compression
- */
- long
- recvfile(fp,s,mode,hash)
- register FILE *fp;
- register int s;
- int mode;
- int hash;
- {
- register int c;
- register long total = 0;
- long hmark = 0;
- int cnt;
- struct usock *up;
- struct mbuf *bp;
-
- if (mode == ASCII_TYPE)
- sockmode(s,SOCK_ASCII);
- else
- sockmode(s,SOCK_BINARY);
- up = itop(s);
- if (mode != ASCII_TYPE && up->zout == NULLLZW) { /* also, not lzw compressed */
- while((cnt = recv_mbuf(s,&bp,0,NULLCHAR,0)) != 0){
- pwait (0); /* be a good neighbor and share! */
- if(cnt == -1){
- total = -1;
- break;
- }
- total += cnt;
- hashit (hash, total, &hmark);
- pwait (0); /* be a good neighbor and share! */
- if(fp != NULLFILE){
- if(write_p(fp,bp) == -1){
- free_p(bp);
- total = -1;
- break;
- }
- free_p(bp);
- } else
- send_mbuf(Curproc->output, bp, 0, NULLCHAR, 0);
- pwait (0); /* be a good neighbor and share! */
- }
- } else {
- while((c = recvchar(s)) != EOF){
- if(fp != NULLFILE){
- #if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA)
- if (mode == ASCII_TYPE) {
- if(c == '\n'){
- /* Needed only if the OS uses a CR/LF
- * convention and putc doesn't do
- * an automatic translation
- */
- putc('\r',fp);
- }
- }
- #endif
- if(putc(c,fp) == EOF){
- total = -1;
- break;
- }
- } else
- tputc((char)c);
- total++;
- hashit (hash, total, &hmark);
- if (!(total % 256))
- pwait (0); /* be a good neighbor and share! */
- }
- }
- /* Detect an abnormal close */
- if(socklen(s,0) == -1)
- total = -1;
- if(hash)
- tputc('\n');
- return total;
- }
- /* Determine if a file appears to be binary (i.e., non-text).
- * Return 1 if binary, 0 if ascii text after rewinding the file pointer.
- *
- * Used by FTP to warn users when transferring a binary file in text mode.
- */
- int
- isbinary(fp)
- FILE *fp;
- {
- int c,i;
- int rval;
-
- rval = 0;
- for(i=0;i<512;i++){
- if((c = getc(fp)) == EOF)
- break;
- if(c & 0x80){
- /* High bit is set, probably not text */
- rval = 1;
- break;
- }
- }
- /* Assume it was at beginning */
- fseek(fp,0L,SEEK_SET);
- return rval;
- }
-
- unsigned long
- getsize(fp)
- FILE *fp;
- {
- fseek(fp,0L,SEEK_END); /* Go to end of file */
- return (unsigned long) ftell(fp); /* Return file pointer position */
- }
-
- /* Compute checksum of the first n bytes */
- unsigned long
- checksum(fp,n)
- FILE *fp;
- long n;
- {
- unsigned long sum;
- long i;
- int c;
-
- rewind(fp);
- sum = 0;
- for(i=1;i<=n;i++){
- if((c = fgetc(fp)) == EOF)
- break;
- sum += (unsigned long)c;
- }
- return sum;
- }
-
- /* Compute MD5 hash of local file */
- int
- md5hash(fp,hash,ascii)
- FILE *fp;
- char hash[16];
- int ascii;
- {
- MD5_CTX md;
- char *buf;
- int len;
-
- MD5Init(&md);
-
- if(ascii){
- /* Text file, hash canonical form (newlines = crlf) */
- char *cp;
- int c;
-
- cp = buf = malloc(MD5BLOCK);
- len = 0;
- while((c = fgetc(fp)) != EOF){
- if(c == '\n'){
- *cp++ = '\r';
- if(++len == MD5BLOCK){
- MD5Update(&md,buf,len);
- pwait(NULL);
- cp = buf;
- len = 0;
- }
- }
- *cp++ = c;
- if(++len == MD5BLOCK){
- MD5Update(&md,buf,len);
- pwait(NULL);
- cp = buf;
- len = 0;
- }
- }
- if(len != 0)
- MD5Update(&md,buf,len);
- free(buf);
- } else {
- buf = malloc(BUFSIZ);
- while((len = fread(buf,1,BUFSIZ,fp)) != 0){
- MD5Update(&md,buf,len);
- pwait(NULL);
- }
- free(buf);
- }
- MD5Final(&md);
- memcpy(hash,md.digest,16);
- return 0;
- }
-
-